package com.chatmcp.mcprouter.service.impl;

import com.chatmcp.mcprouter.config.McpServersConfig;
import com.chatmcp.mcprouter.config.RemoteApisConfig;
import com.chatmcp.mcprouter.dto.ServerConfigDto;
import com.chatmcp.mcprouter.mapper.ServerKeyMapper;
import com.chatmcp.mcprouter.model.ServerKey;
import com.chatmcp.mcprouter.service.CacheService;
import com.chatmcp.mcprouter.service.McpServerService;
import com.chatmcp.mcprouter.util.HashUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * MCP服务器服务实现类
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class McpServerServiceImpl implements McpServerService {

    private static final String SERVER_CONFIG_CACHE_PREFIX = "server_config:";
    private static final long SERVER_CONFIG_CACHE_TTL = 24 * 60 * 60; // 24小时

    private final CacheService cacheService;
    private final McpServersConfig mcpServersConfig;
    private final RemoteApisConfig remoteApisConfig;
    private final ServerKeyMapper serverKeyMapper;
    private final RestTemplate restTemplate;

    @Override
    public ServerConfigDto getServerConfig(String key) {
        if (key == null || key.isEmpty()) {
            return null;
        }

        // 先从缓存获取
        String cacheKey = SERVER_CONFIG_CACHE_PREFIX + key;
        ServerConfigDto cachedConfig = cacheService.get(cacheKey, ServerConfigDto.class);
        if (cachedConfig != null) {
            return cachedConfig;
        }

        // 从数据库获取
        ServerKey serverKey = serverKeyMapper.selectByKey(key);
        if (serverKey != null) {
            // 创建DTO
            ServerConfigDto config = convertToDto(serverKey);
            
            // 如果有项目UUID，应该查找项目信息并补充
            if (serverKey.getServerUuid() != null && !serverKey.getServerUuid().isEmpty()) {
                try {
                    // 查找项目 - 这里应添加相应的项目查询逻辑
                    // Project project = projectMapper.selectByUuid(serverKey.getServerUuid());
                    // if (project != null) {
                    //     config.setServerType(project.getSseProvider());
                    //     config.setServerUrl(project.getSseUrl());
                    // }
                } catch (Exception e) {
                    log.error("Failed to find project for serverKey {}: {}", key, e.getMessage());
                }
            }
            
            // 保存到缓存
            cacheService.set(cacheKey, config, SERVER_CONFIG_CACHE_TTL, TimeUnit.SECONDS);
            return config;
        }

        // 从配置文件获取
        McpServersConfig.ServerConfig serverConfig = mcpServersConfig.getServers().get(key);
        if (serverConfig != null) {
            ServerConfigDto config = convertToDto(key, serverConfig);
            // 保存到数据库
            saveServerConfig(config);
            // 保存到缓存
            cacheService.set(cacheKey, config, SERVER_CONFIG_CACHE_TTL, TimeUnit.SECONDS);
            return config;
        }

        // 从远程API获取 - 使用POST请求而不是GET
        if (remoteApisConfig.getGetServerConfig() != null && !remoteApisConfig.getGetServerConfig().isEmpty()) {
            try {
                // 准备请求头
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                
                // 准备请求体
                Map<String, String> requestBody = new HashMap<>();
                requestBody.put("server_key", key);
                
                // 创建请求实体
                HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(requestBody, headers);
                
                // 发送POST请求
                ResponseEntity<ServerConfigDto> response = restTemplate.postForEntity(
                        remoteApisConfig.getGetServerConfig(),
                        requestEntity,
                        ServerConfigDto.class);
                
                if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                    ServerConfigDto config = response.getBody();
                    
                    // 如果没有CommandHash但有Command，计算哈希
                    if (config.getCommand() != null && !config.getCommand().isEmpty() && 
                        (config.getCommandHash() == null || config.getCommandHash().isEmpty())) {
                        config.setCommandHash(HashUtil.md5(config.getCommand()));
                    }
                    
                    // 保存到数据库
                    saveServerConfig(config);
                    // 保存到缓存
                    cacheService.set(cacheKey, config, SERVER_CONFIG_CACHE_TTL, TimeUnit.SECONDS);
                    return config;
                }
            } catch (Exception e) {
                log.error("Failed to get server config from remote API: {}", e.getMessage());
            }
        }

        return null;
    }

    @Override
    public boolean refreshServerConfig(String key) {
        if (key == null || key.isEmpty()) {
            // 刷新所有缓存
            // 实际操作中可能需要获取所有键并遍历刷新
            return true;
        } else {
            // 删除指定键的缓存
            String cacheKey = SERVER_CONFIG_CACHE_PREFIX + key;
            return cacheService.delete(cacheKey);
        }
    }

    @Override
    public Map<String, ServerConfigDto> getAllServerConfigs() {
        // 从数据库获取所有服务器配置
        Map<String, ServerConfigDto> configMap = new HashMap<>();
        
        // 查询所有ServerKey记录
        serverKeyMapper.selectAll().forEach(serverKey -> {
            ServerConfigDto config = convertToDto(serverKey);
            configMap.put(serverKey.getKey(), config);
        });
        
        // 合并配置文件中的配置
        if (mcpServersConfig.getServers() != null) {
            mcpServersConfig.getServers().forEach((key, serverConfig) -> {
                if (!configMap.containsKey(key)) {
                    ServerConfigDto config = convertToDto(key, serverConfig);
                    configMap.put(key, config);
                }
            });
        }
        
        return configMap;
    }

    /**
     * 将ServerKey实体转换为DTO
     *
     * @param serverKey ServerKey实体
     * @return ServerConfigDto
     */
    private ServerConfigDto convertToDto(ServerKey serverKey) {
        return ServerConfigDto.builder()
                .serverKey(serverKey.getKey())
                .serverUuid(serverKey.getServerUuid())
                .serverName(serverKey.getServerName())
                .serverType(serverKey.getServerType())
                .serverUrl(serverKey.getServerUrl())
                .command(serverKey.getCommand())
                .commandHash(serverKey.getCommandHash())
                .shareProcess(serverKey.getShareProcess())
                .build();
    }

    /**
     * 将配置文件中的ServerConfig转换为DTO
     *
     * @param key          键名
     * @param serverConfig 配置文件中的ServerConfig
     * @return ServerConfigDto
     */
    private ServerConfigDto convertToDto(String key, McpServersConfig.ServerConfig serverConfig) {
        return ServerConfigDto.builder()
                .serverKey(key)
                .serverUuid(UUID.randomUUID().toString())
                .serverName(key)
                .serverType(serverConfig.getServerType())
                .serverUrl(serverConfig.getServerUrl())
                .command(serverConfig.getCommand())
                .commandHash(serverConfig.getCommand() != null ? HashUtil.md5(serverConfig.getCommand()) : null)
                .shareProcess(serverConfig.getShareProcess())
                .build();
    }

    /**
     * 保存服务器配置到数据库
     *
     * @param config 服务器配置DTO
     */
    private void saveServerConfig(ServerConfigDto config) {
        // 检查是否已存在
        ServerKey existingServerKey = serverKeyMapper.selectByKey(config.getServerKey());
        ServerKey serverKey;
        if (existingServerKey != null) {
            serverKey = existingServerKey;
        } else {
            serverKey = new ServerKey();
            serverKey.setKey(config.getServerKey());
        }

        serverKey.setServerUuid(config.getServerUuid());
        serverKey.setServerName(config.getServerName());
        serverKey.setServerType(config.getServerType());
        serverKey.setServerUrl(config.getServerUrl());
        serverKey.setCommand(config.getCommand());
        serverKey.setCommandHash(config.getCommandHash());
        serverKey.setShareProcess(config.getShareProcess());

        if (existingServerKey != null) {
            serverKeyMapper.update(serverKey);
        } else {
            serverKeyMapper.insert(serverKey);
        }
    }
} 